package com.evil.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.account.api.RemoteUserEnterpriseService;
import com.evil.account.mapper.EnterpriseMapper;
import com.evil.account.mapper.UserEnterpriseMapper;
import com.evil.account.pojo.dto.enterprise.EnterpriseBaseInfoResp;
import com.evil.account.pojo.dto.user.enterprise.AddUserEnterpriseDTO;
import com.evil.account.pojo.entity.Enterprise;
import com.evil.account.pojo.entity.UserEnterprise;
import com.evil.account.service.UserEnterpriseService;
import com.evil.common.account.dto.user.*;
import com.evil.common.account.dto.user.enterprise.EnterpriseUsersReqDTO;
import com.evil.common.account.dto.user.enterprise.MineEnterprisesReqDTO;
import com.evil.common.account.enums.IsManageEnum;
import com.evil.common.account.util.LoginUtil;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.enums.SwitchEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.StreamUtil;
import com.evil.common.file.dto.FileRespDTO;
import com.evil.file.api.RemoteFileService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户企业表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@RestController
@AllArgsConstructor
public class UserEnterpriseServiceImpl extends ServiceImpl<UserEnterpriseMapper, UserEnterprise> implements UserEnterpriseService, RemoteUserEnterpriseService {

    private final LoginUtil loginUtil;

    private final EnterpriseMapper enterpriseMapper;

    private final RemoteFileService remoteFileService;

    private final AccountLogServiceImpl accountLogService;

    /**
     * 获取当前用户企业列表
     *
     * @return BaseEnterpriseDTO
     */
    @Override
    public List<EnterpriseBaseInfoResp> mineEnterprises(MineEnterprisesReqDTO mineEnterprisesReqDTO) {
        UserBaseRespDTO loginUserBase = loginUtil.getLoginUserBase();
        List<UserEnterprise> userEnterprises = this.baseMapper.findUserEnterprises(loginUserBase.getUserId(), mineEnterprisesReqDTO);
        Set<Long> enterpriseIds = StreamUtil.transSetT(userEnterprises, UserEnterprise::getEnterpriseId);

        List<Enterprise> enterprises = enterpriseMapper.findByIds(enterpriseIds, true);
        // 过滤平台类型
        if (null != mineEnterprisesReqDTO.getPlatformType()) {
            enterprises = StreamUtil.filter(enterprises, e -> mineEnterprisesReqDTO.getPlatformType().equals(e.getPlatformType()));
        }
        Set<Long> fileIds = new HashSet<>();
        enterprises.forEach(e -> {
            Optional.ofNullable(e.getLoginLogoFileId()).ifPresent(fileIds::add);
            Optional.ofNullable(e.getSystemLogoFileId()).ifPresent(fileIds::add);
            Optional.ofNullable(e.getExportLogoFileId()).ifPresent(fileIds::add);
        });
        Map<Long, FileRespDTO> fileMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(fileIds)) {
            fileMap.putAll(remoteFileService.findBaseMapByFileIds(fileIds));
        }

        return enterprises.stream().map(e -> {
            EnterpriseBaseInfoResp baseInfoResp = BeanUtil.copyProperties(e, EnterpriseBaseInfoResp.class);
            baseInfoResp.setLoginLogoFile(fileMap.get(e.getLoginLogoFileId()));
            baseInfoResp.setSystemLogoFile(fileMap.get(e.getSystemLogoFileId()));
            baseInfoResp.setExportLogoFile(fileMap.get(e.getExportLogoFileId()));
            return baseInfoResp;
        }).collect(Collectors.toList());
    }

    /**
     * 获取企业用户ids
     *
     * @param findUserIdsByIdReqDTO findUserIdsByIdReqDTO
     * @return BaseEnterpriseDTO
     */
    @Override
    public List<Long> enterpriseUserIds(FindUserIdsByIdReqDTO findUserIdsByIdReqDTO) {
        // 如果需要缓存，则在此if判断实现
        return this.baseMapper.enterpriseUserIds(findUserIdsByIdReqDTO);
    }

    /**
     * 检查企业正常用户
     *
     * @param checkEnterpriseUserIdsReqDTO checkEnterpriseUserIdsReqDTO
     * @return BaseEnterpriseDTO
     */
    @Override
    public List<Long> checkEnterpriseUserIds(CheckEnterpriseUserIdsReqDTO checkEnterpriseUserIdsReqDTO) {
        return this.baseMapper.checkEnterpriseUserIds(checkEnterpriseUserIdsReqDTO);
    }

    /**
     * 获取企业用户基础信息列表
     *
     * @param findUserIdsByIdReqDTO findUserIdsByIdReqDTO
     * @return BaseEnterpriseDTO
     */
    @Override
    public List<UserBaseRespDTO> enterpriseUserBases(FindUserIdsByIdReqDTO findUserIdsByIdReqDTO) {
        // 如果需要缓存，则在此if判断实现
        return this.baseMapper.enterpriseUserBases(findUserIdsByIdReqDTO);
    }

    /**
     * 设置用户在当前企业中是否禁用
     *
     * @param enableUsersReqDTO enableUserReqDTO
     */
    @Override
    public void enable(EnableUsersReqDTO enableUsersReqDTO) {
        // 检查企业管理员
        this.checkEnterpriseManager(loginUtil.getLoginUserEnterprise());

        Integer isEnabled = enableUsersReqDTO.getIsEnabled();
        Set<Long> userIds = new HashSet<>(enableUsersReqDTO.getUserIds());
        Long enterpriseId = loginUtil.getParamEnterpriseId(enableUsersReqDTO.getEnterpriseId());

        enterpriseMapper.findNormalById(enterpriseId);

        List<UserEnterprise> userEnterprises = this.baseMapper.findEnterpriseUsersByEIdAndUIds(enterpriseId, userIds, true);
        userEnterprises.forEach(ue -> ue.setIsEnable(isEnabled));

        accountLogService.saveBatchAndCheck(this.baseMapper, UserEnterprise::getUserEnterpriseId, userEnterprises);
    }

    /**
     * 删除用户在当前企业的信息
     *
     * @param enterpriseUsersReqDTO enterpriseUsersReqDTO
     */
    @Override
    public void deleteUserEnterpriseBatch(EnterpriseUsersReqDTO enterpriseUsersReqDTO) {
        List<Long> userIds = enterpriseUsersReqDTO.getUserIds();
        Long enterpriseId = loginUtil.getParamEnterpriseId(enterpriseUsersReqDTO.getEnterpriseId());

        enterpriseMapper.findNormalById(enterpriseId);

        List<UserEnterprise> userEnterprises = this.baseMapper.findEnterpriseUsersByEIdAndUIds(enterpriseId, userIds, true);
        userEnterprises.forEach(e -> e.setIsDeleted(SwitchEnum.YES.getId()));
        accountLogService.saveBatchAndCheck(this.baseMapper, UserEnterprise::getUserEnterpriseId, userEnterprises);
    }

    /**
     * 检查企业人员状态
     *
     * @param userEnterpriseDTO userEnterpriseDTO
     */
    @Override
    public void checkEnterpriseUser(UserEnterpriseDTO userEnterpriseDTO) {
        this.baseMapper.findNormalByEIdAndUId(userEnterpriseDTO.getEnterpriseId(), userEnterpriseDTO.getEnterpriseId());
    }

    /**
     * 是否企业管理员
     *
     * @param userEnterpriseDTO userEnterpriseDTO
     * @return boolean
     */
    @Override
    public Boolean enterpriseManager(UserEnterpriseDTO userEnterpriseDTO) {
        Long enterpriseId = userEnterpriseDTO.getEnterpriseId();
        Long userId = userEnterpriseDTO.getUserId();
        return IsManageEnum.MANAGE.getId() == this.findByEIdAndUId(enterpriseId, userId).getIsManager();
    }

    /**
     * 是否企业管理员
     *
     * @param userEnterpriseDTO userEnterpriseDTO
     * @return boolean
     */
    @Override
    public boolean isEnterpriseManager(UserEnterpriseDTO userEnterpriseDTO) {
        UserEnterprise userEnterprise = this.baseMapper.findByEIdAndUId(userEnterpriseDTO.getEnterpriseId(), userEnterpriseDTO.getUserId());
        return IsManageEnum.MANAGE.getId() == userEnterprise.getIsManager();
    }

    /**
     * 检查企业管理员
     *
     * @param userEnterpriseDTO userEnterpriseDTO
     */
    @Override
    public void checkEnterpriseManager(UserEnterpriseDTO userEnterpriseDTO) {
        if (!this.enterpriseManager(userEnterpriseDTO)) {
            throw new BusinessException(RCodeEnum.ERROR_UNAUTHORIZED);
        }
    }

    /**
     * 获取用户企业
     *
     * @param enterpriseId enterpriseId
     * @param userId       userId
     * @return UserEnterprise
     */
    @Override
    public Optional<UserEnterprise> isExistByEIdAndUId(Long enterpriseId, Long userId) {
        return this.baseMapper.isExistByEIdAndUId(enterpriseId, userId);
    }

    /**
     * 获取用户企业
     *
     * @param enterpriseId enterpriseId
     * @param userId       userId
     * @return UserEnterprise
     */
    @Override
    public UserEnterprise findByEIdAndUId(Long enterpriseId, Long userId) {
        return this.baseMapper.findByEIdAndUId(enterpriseId, userId);
    }

    /**
     * 获取用户的用户企业列表
     *
     * @param userId userId
     * @return UserEnterprise 列表
     */
    @Override
    public List<UserEnterprise> findUserEnterprises(Long userId) {
        return this.baseMapper.findUserEnterprises(userId, null);
    }

    /**
     * 获取企业的用户企业列表
     *
     * @param enterpriseId enterpriseId
     * @return UserEnterprise 列表
     */
    @Override
    public List<UserEnterprise> findEnterpriseUsers(Long enterpriseId) {
        return this.baseMapper.findEnterpriseUsers(enterpriseId);
    }

    /**
     * 新增用户企业
     *
     * @param addUserEnterpriseReqDTO addUserEnterpriseReqDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUserEnterprise(AddUserEnterpriseDTO addUserEnterpriseReqDTO) {
        Long userId = addUserEnterpriseReqDTO.getUserId();
        Long enterpriseId = addUserEnterpriseReqDTO.getEnterpriseId();

        enterpriseMapper.findNormalById(enterpriseId);

        // 企业管理员
        this.checkEnterpriseManager(loginUtil.getLoginUserEnterprise());

        UserEnterprise userEnterprise = this.baseMapper.isExistByEIdAndUId(enterpriseId, userId)
                .map(e -> {
                    if (SwitchEnum.isOpen(e.getIsDeleted())) {
                        log.info("【创建用户企业-创建用户企业信息】已有用户企业，但是已被删除，作还原处理，用户id：{}，企业id:{}", userId, enterpriseId);
                        return e;
                    } else {
                        log.info("【创建用户企业-创建用户企业信息】已有用户企业，用户id：{}，企业id:{}", userId, enterpriseId);
                        throw new BusinessException(RCodeEnum.USER_IN_ENTERPRISE_IS_EXIST, "该成员已存在");
                    }
                })
                .orElseGet(() -> {
                    log.info("【创建用户企业-创建用户企业信息】用户企业不存在，用户id：{}，企业id:{}", userId, enterpriseId);
                    return this.createUserEnterprise(userId, enterpriseId, addUserEnterpriseReqDTO.getUserCode());
                });
        userEnterprise.setIsDeleted(SwitchEnum.NO.getId());
        // 默认非管理员
        userEnterprise.setIsDefault(SwitchEnum.NO.getId());
        userEnterprise.setIsManager(IsManageEnum.UN_MANAGE.getId());
        accountLogService.saveAndCheck(this.baseMapper, UserEnterprise::getUserEnterpriseId, userEnterprise);
    }

    /**
     * 修改登录用户基础信息
     *
     * @param userBaseReqDTO userBaseReqDTO
     */
    @Override
    public void modifyBaseInfo(UserBaseReqDTO userBaseReqDTO) {
        UserEnterpriseDTO loginUserEnterprise = loginUtil.getLoginUserEnterprise();
        UserEnterprise userEnterprise = this.findByEIdAndUId(loginUserEnterprise.getEnterpriseId(), loginUserEnterprise.getUserId());
        userEnterprise.setUserCode(userBaseReqDTO.getUserCode());
        userEnterprise.setNickName(userBaseReqDTO.getNickName());

        accountLogService.saveAndCheck(this.baseMapper, UserEnterprise::getUserEnterpriseId, userEnterprise);
    }

    /**
     * 创建用户企业
     *
     * @param userId       userId
     * @param enterpriseId enterpriseId
     * @return UserEnterprise
     */
    private UserEnterprise createUserEnterprise(Long userId, Long enterpriseId, String code) {
        UserEnterprise userEnterprise = new UserEnterprise();
        userEnterprise.setUserId(userId);
        userEnterprise.setEnterpriseId(enterpriseId);
        userEnterprise.setIsDefault(SwitchEnum.NO.getId());
        userEnterprise.setIsManager(IsManageEnum.UN_MANAGE.getId());
        userEnterprise.setUserCode(code);
        return userEnterprise;
    }
}
